package com.e3.sysmg.security.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.e3.sysmg.security.model.ModuleModel;
import com.e3.sysmg.security.model.RoleModel;
import com.e3.web.widget.client.MyField;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.DataProxy;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.ModelReader;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.StoreSorter;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.form.DualListField;
import com.extjs.gxt.ui.client.widget.form.Field;
import com.extjs.gxt.ui.client.widget.form.FieldSet;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.ListField;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class RoleFormPanel extends LayoutContainer {

	private Map<String,Field<?>> formFieldMaps = new HashMap<String, Field<?>>();

	private RoleRPCServiceAsync service = RoleRPCService.Util.getInstance();
	
	private FormPanel formPanel;
	
	private FormData formData = new FormData("100%");
		
	private ListField<RoleModel> fromList;
	private ListField<RoleModel> toList;
	
	private RoleModuleGridField gridField = new RoleModuleGridField();
	
	private List<RoleModel> fromDatas = new ArrayList<RoleModel>();
	
	private RoleModel roleModel;
	
	private final RoleFormPanel roleFormPanel = this;
	
	public RoleFormPanel() {
	}

	@Override
	protected void onRender(Element parent, int index) {
		super.onRender(parent, index);
		this.setLayout(new FitLayout());
		
		this.add(getFormPanel());
		
	}
	
	private FormPanel getFormPanel(){
		if(formPanel == null){
			formPanel = new FormPanel();
			formPanel.setHeaderVisible(false);
			initFormPanel(formPanel);
		}
		return formPanel;
	}
	
	private void initFormPanel(FormPanel form){
		FieldSet fieldSet = getBaseInfoFields();
		form.add(fieldSet);
		
		fieldSet = getParentRolesField();
		form.add(fieldSet);
		
		fieldSet = getRoleModulesField();
		form.add(fieldSet);
	}
	
	private FieldSet getBaseInfoFields(){
		FieldSet fieldSet = new FieldSet();
		fieldSet.setHeading("基本信息");
		fieldSet.setLayout(new FormLayout());
		
		String[] names = {RoleModel.ID, RoleModel.CODE,RoleModel.NAME,RoleModel.DESCRIPTION};
		for (String name : names) {
			Field<?> field = RoleHelper.INSTANCE.INSTANCE.createFormField(name);
			fieldSet.add(field,formData);
			formFieldMaps.put(name, field);
		}
		return fieldSet;
	}
	
	private FieldSet getParentRolesField(){
		FieldSet fieldSet = new FieldSet();
		fieldSet.setHeading("继承角色");
		fieldSet.setLayout(new FitLayout());
		
		final DualListField<RoleModel> lists = new DualListField<RoleModel>();
		fromList = lists.getFromList();  
		mask("正在加载数据");
	    fromList.setDisplayField(RoleModel.NAME);  
	    
	    DataProxy<List<RoleModel>> proxy = new RpcProxy<List<RoleModel>>() {
			@Override
			protected void load(Object loadConfig,AsyncCallback<List<RoleModel>> callback) {
				service.getAllRoles(callback);
			}
		};
		
	    ListLoader<ListLoadResult<RoleModel>> loader = new BaseListLoader<ListLoadResult<RoleModel>>(proxy,new ModelReader()) {
	    	
			@Override
			protected void onLoadSuccess(Object loadConfig,ListLoadResult<RoleModel> data) {
				fromDatas = data.getData();
				if(roleFormPanel.roleModel!=null){
					List<RoleModel> datas = data.getData();
					List<RoleModel> pRoles = roleFormPanel.roleModel.getParentRoles();
					if(pRoles!=null&&pRoles.size()>0){
						for (RoleModel rm : pRoles) {
							datas.remove(rm);
						}
					}
				}
				super.onLoadSuccess(loadConfig, data);
				unmask();
			}

			@Override
			protected void onLoadFailure(Object loadConfig, Throwable t) {
				super.onLoadFailure(loadConfig, t);
				unmask();
			}
	    	
	    };
	    ListStore<RoleModel> store = new ListStore<RoleModel>(loader);
	    store.setStoreSorter(new StoreSorter<RoleModel>());  
	    store.setModelComparer(RoleHelper.INSTANCE.getModelComparer());
	    store.setKeyProvider(RoleHelper.INSTANCE.getModelKeyProvider());
	    fromList.setStore(store); 
	    loader.load();
	    
	    toList = lists.getToList();  
	    toList.setDisplayField(RoleModel.NAME);  
	    store = new ListStore<RoleModel>();  
	    store.setStoreSorter(new StoreSorter<RoleModel>());  
	    store.setModelComparer(RoleHelper.INSTANCE.getModelComparer());
	    store.setKeyProvider(RoleHelper.INSTANCE.getModelKeyProvider());
	    toList.setStore(store);  
	    
	    fieldSet.add(lists);
	    return fieldSet;
	}
	
	private FieldSet getRoleModulesField(){
		FieldSet fieldSet = new FieldSet();
		fieldSet.setHeading(RoleMessages.INSTANCE.title_authed_modules());
		fieldSet.setLayout(new FitLayout());
		
		fieldSet.add(gridField);
				
		fieldSet.setHeight(275);
		return fieldSet;
	}

	public void setFormValue(RoleModel roleModel){
		this.roleModel = roleModel;
		clearFormData();
		if(roleModel == null){
			return;
		}
		
		String[] fieldNames = {RoleModel.ID,RoleModel.CODE,RoleModel.NAME,RoleModel.DESCRIPTION};
		for (String fn : fieldNames) {
			Object value = roleModel.get(fn);
			MyField field = (MyField)formFieldMaps.get(fn);
			field.setFieldValue(value);
		}
		List<RoleModel> pRoles = roleModel.getParentRoles();
		if(pRoles!=null){
			toList.getStore().add(pRoles);
		}
		fromList.getStore().remove(roleModel);
		if(pRoles!=null){
			for (RoleModel rm : pRoles) {
				fromList.getStore().remove(rm);
			}
		}
		
		List<ModuleModel> authedModules = roleModel.getAuthedModules();
		if(authedModules!=null){
			gridField.setAuthedModules(authedModules);
		}
	}
	
	public RoleModel getFormValue(){
		RoleModel role = roleModel;
		if(role == null){
			role = new RoleModel();
		}
		
		String[] fieldNames = {RoleModel.ID,RoleModel.CODE,RoleModel.NAME,RoleModel.DESCRIPTION};
		for (String fn : fieldNames) {
			MyField field = (MyField)formFieldMaps.get(fn);
			role.set(fn, field.getFieldValue());
		}
		List<RoleModel> pRoles = toList.getSelection();
		role.setParentRoles(pRoles);
		
		List<ModuleModel> modules = gridField.getAuthedModules();
		role.setAuthedModules(modules);
		return role;
	}

	public void clearFormData(){
		getFormPanel().clear();
		toList.getStore().removeAll();
		fromList.getStore().removeAll();
		if(fromDatas == null||fromDatas.isEmpty()){
			fromList.getStore().getLoader().load();
		}
		else{
			fromList.getStore().add(fromDatas);
		}
	}
	
	public void addRoleToFromList(RoleModel roleModel){
		fromList.getStore().add(roleModel);
		fromDatas.add(roleModel);
	}
	
	public void updateFromListData(RoleModel roleModel){
		fromList.getStore().update(roleModel);
		for (int i=0;i<fromDatas.size();i++ ) {
			RoleModel role = fromDatas.get(i);
			if(role.getId().equals(roleModel.getId())){
				fromDatas.remove(role);
				fromDatas.add(i, roleModel);
				break;
			}
		}
	}
	
	public void removeFromListData(List<RoleModel> models){
		for (RoleModel roleModel : models) {
			for (RoleModel role : fromDatas) {
				if(role.getId().equals(roleModel.getId())){
					fromDatas.remove(role);
					break;
				}
			}
		}
	}
}
